#include "DataStructure/Input/Constraint/MPCData.h"

#include "DataStructure/Common/Id.h"
#include "DataStructure/Common/Real.h"
#include "DataStructure/Common/Validation.h"
#include "DataStructure/Input/Solver/DOFDirections.h"

using namespace SG::DataStructure;

/// @brief 设置方程中从节点相关项
/// @param node
/// @param dof
/// @param factor
void FEM::MPCData::SetSlaveItem (const SG::DataStructure::Common::Id&         node,
                                 const SG::DataStructure::FEM::DOFDirections& dof,
                                 const SG::DataStructure::Common::Real&       factor)
{
    m_slaveItem.m_nodeId = node;
    m_slaveItem.m_dof    = dof;
    m_slaveItem.m_factor = factor;
}

/// @brief 添加主节点有关项
/// @param node
/// @param dof
/// @param factor
void FEM::MPCData::AddMasterItem (const SG::DataStructure::Common::Id&         node,
                                  const SG::DataStructure::FEM::DOFDirections& dof,
                                  const SG::DataStructure::Common::Real&       factor)
{
    m_masterItems.push_back (MPCComponent{ node, dof, factor });
}

/// @brief 判断两个MPCComponent是否相等
/// @param lhs
/// @param rhs
/// @return
bool SG::DataStructure::FEM::operator== (const MPCData::MPCComponent& lhs, const MPCData::MPCComponent& rhs)
{
    if (lhs.m_nodeId != rhs.m_nodeId)
    {
        return false;
    }
    if (!SG::DataStructure::Common::isNear (lhs.m_factor, rhs.m_factor))
    {
        return false;
    }
    if (lhs.m_dof != rhs.m_dof)
    {
        return false;
    }
    return true;
}

/// @brief 判断两个MPCData是否相等
/// @param lhs
/// @param rhs
/// @return
bool SG::DataStructure::FEM::operator== (const MPCData& lhs, const MPCData& rhs)
{
    if (lhs.m_sId != rhs.m_sId)
    {
        return false;
    }
    if (lhs.m_masterItems != rhs.m_masterItems)
    {
        return false;
    }
    if (lhs.m_domainId != rhs.m_domainId)
    {
        return false;
    }
    if (!(lhs.m_slaveItem == rhs.m_slaveItem))
    {
        return false;
    }
    return true;
}

/// @brief 比较两个MPCData大小
/// @param lhs
/// @param rhs
/// @return
bool FEM::operator< (const MPCData& SGDataA, const MPCData& SGDataB)
{
    return SGDataA.m_sId < SGDataB.m_sId;
}